package controller.trafficlights;

import controller.JSONSender;
import simulator.enums.Direction;
import simulator.enums.LaneType;

public abstract class TrafficLight 
{
	public enum TrafficLightState
	{
		green, red, yellow, blink, off;
	}
	
	protected Direction _direction;
	protected LaneType _type;
	protected TrafficLightState _state;
	protected int _count;
	protected Boolean _isActive;
	protected long _waitingTime = 0;
	protected long _elapsedTime = 0;
	protected int _priority = 0;
	
	/**
	 * Updates the color of the lights when active.
	 * @param elapsedTime The elapsed time in miliseconds.
	 */
	public abstract void update(long elapsedTime);
	
	/**
	 * Updates the priority according to waiting time.
	 * @param elapsedTime The elapsed time in miliseconds.
	 */
	public abstract void updatePriority(long elapsedTime);
	
	/**
	 * Checks if a lights is compatible with another light, meaning that they can be on at the same time.
	 * @param trafficLight The light to compare with.
	 * @return
	 */
	public abstract boolean isCompatibleWith(TrafficLight trafficLight);
	
	public void changeState(TrafficLightState newState)
	{
		_state = newState;
		JSONSender.addToSendList(_direction.getName(), _type.getID(), _state.name());
		if(_state == TrafficLightState.red)
		{
			_isActive = false;
		}
	}
	
	public void activate()
	{
		_isActive = true;
	}
	
	public void loopEntered()
	{
		_count++;
	}
	
	public void loopLeft()
	{
		_count--;
		if(_count == 0)
		{
			_waitingTime = 0;
			if(_state == TrafficLightState.green)
			{
				_elapsedTime += 5000;
			}
		}
	}
	
	public TrafficLightState getState()
	{
		return _state;
	}
	
	public Boolean isOccupied()
	{
		return _count > 0;
	}
	
	public Direction getDirection()
	{
		return _direction;
	}
	
	public LaneType getLaneType()
	{
		return _type;
	}
	
	public void setPriority(int priority)
	{
		_priority = priority;
	}
	
	/**
	 * Indicates whether this light is active or not, inactive would mean that its state
	 * isn't going to change
	 * @return True if the light is active.
	 */
	public Boolean isActive()
	{
		return _isActive;
	}
	
	public String toString()
	{
		return _direction + " " + _type + " priority: " + _priority;
	}
}
